/******************************************************************************
 * Copyright (C) 2011 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;

import org.apache.log4j.Logger;

import com.sun.xml.internal.ws.util.UtilException;


/**
 * 用于远程获取domains信息 对domains的操作
 * 
 * @author 陈大周
 * @since jdk1.5
 * @version 2011-04-18 陈大周 新建
 */
public class RemoteServerUilts {
    
    /** log4j对象 */
    private final static Logger LOGGER = Logger.getLogger(RemoteServerUilts.class);
    
    /** MBServer连接 */
    private MBeanServerConnection connection;
    
    /** JMX连接 */
    private JMXConnector connector;
    
    /** jndi名 */
    private static final ObjectName SERVICE;
    
    /**
     * 初始化domains对象
     */
    static {
        try {
            SERVICE =
                new ObjectName(
                    "com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
        } catch (MalformedObjectNameException e) {
            LOGGER.error("初始化domains对象失败", e);
            throw new AssertionError(e.getMessage());
        }
    }
    
    /**
     * 初始化weblogic连接
     * 
     * @param hostname ip
     * @param portString 端口
     * @param username 用户名
     * @param password 密码
     * @param strServiceThread
     * @throws MalformedURLException 异常
     * @throws IOException 异常
     */
    public RemoteServerUilts(String hostname, String portString, String username, String password,
        String strServiceThread) throws Exception {
        initConnection(hostname, portString, username, password, strServiceThread);
    }
    
    /**
     * 初始化weblogic的连接
     * 
     * @param hostname ip
     * @param portString 端口
     * @param username 用户名
     * @param password 密码
     * @param strServiceThread
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public void initConnection(String hostname, String portString, String username, String password,
        String strServiceThread) throws Exception {
        // try {
        String strPotocol = "t3";
        Integer objPortInteger = Integer.valueOf(portString);
        int iPort = objPortInteger.intValue();
        String strJndiroot = "/jndi/";
        String strMserver = "weblogic.management.mbeanservers.runtime";
        JMXServiceURL objServiceURL = new JMXServiceURL(strPotocol, hostname, iPort, strJndiroot + strMserver);
        Thread.currentThread().setName(strServiceThread);
        Map objH = new Hashtable();
        objH.put(Context.SECURITY_PRINCIPAL, username);
        objH.put(Context.SECURITY_CREDENTIALS, password);
        objH.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
        objH.put("jmx.remote.x.request.waiting.timeout", new Long(3000));
        // connector = JMXConnectorFactory.connect(objServiceURL, objH);
        connector = connectWithTimeout(objServiceURL, 3, TimeUnit.SECONDS, objH);
        // connector = JMXConnectorFactory.connect(objServiceURL, objH);
        connection = connector.getMBeanServerConnection();
    }
    
    // public BlockingQueue<Object> mailbox = new ArrayBlockingQueue<Object>(1);
    
    @SuppressWarnings("unchecked")
    JMXConnector connectWithTimeout(JMXServiceURL url, long timeout, TimeUnit unit, Map objH) {
        BlockingQueue<Object> mailbox = new ArrayBlockingQueue<Object>(1);
        Thread objThread = new Thread(new ConnectTimeout(mailbox, url, objH));
        objThread.start();
        Object result = null;
        try {
            result = mailbox.poll(timeout, unit);
            if (result == null) {
                if (!mailbox.offer("")) {
                    result = mailbox.take();
                }
            }
        } catch (InterruptedException e) {
        }
        return (JMXConnector) result;
    }
    
    static class ConnectTimeout implements Runnable {
        
        BlockingQueue<Object> mailbox = null;
        
        JMXServiceURL url = null;
        
        @SuppressWarnings("unchecked")
        Map objH = null;
        
        @SuppressWarnings("unchecked")
        ConnectTimeout(BlockingQueue<Object> mailbox, JMXServiceURL url, Map objH) {
            this.mailbox = mailbox;
            this.url = url;
            this.objH = objH;
        }
        
        @SuppressWarnings("unchecked")
        public void run() {
            JMXConnector connector;
            try {
                connector = JMXConnectorFactory.connect(url, objH);
                mailbox.offer(connector);
            } catch (IOException e) {
            }
        }
    }
    
    public static void main(String args[]) {
        System.out.println(testServerConnection("10.10.28.220"));
    }
    
    /**
     * 获取服务器对象
     * 
     * @return 服务器对象
     * @throws UtilException UtilException
     * @throws AttributeNotFoundException AttributeNotFoundException
     * @throws InstanceNotFoundException InstanceNotFoundException
     * @throws MBeanException MBeanException
     * @throws ReflectionException ReflectionException
     * @throws IOException IOException
     */
    public ObjectName getServerRuntime() throws UtilException, AttributeNotFoundException, InstanceNotFoundException,
        MBeanException, ReflectionException, IOException {
        if (null != connection) {
            return (ObjectName) connection.getAttribute(SERVICE, "ServerRuntime");
        } else {
            return null;
        }
    }
    
    /**
     * 获取weblogic状态
     * 
     * @return 服务状态
     */
    public int testServiceIsOk() {
        /**
         * 0是running，1是warning,2是unknown, 3是远程连不通状态（可能是用户名，密码， IP地址，端口或者网络连不通的情况）
         */
        int iSOk = 3;
        try {
            // weblogic状态为
            // ObjectName[] serverRT = getServerRuntimes();
            ObjectName objSrverRT = getServerRuntime();
            if (objSrverRT != null) {
                String strServerState = (String) connection.getAttribute(objSrverRT, "State");// 运行状态
                if (strServerState.equalsIgnoreCase("running")) {
                    iSOk = 0;
                } else if (strServerState.equalsIgnoreCase("warning")) {
                    iSOk = 1;
                } else {
                    iSOk = 2;
                }
            }
        } catch (UtilException e) {
            LOGGER.error("获取weblogic服务状态失败", e);
        } catch (AttributeNotFoundException e) {
            LOGGER.error("获取weblogic服务状态失败", e);
        } catch (InstanceNotFoundException e) {
            LOGGER.error("获取weblogic服务状态失败", e);
        } catch (MBeanException e) {
            LOGGER.error("获取weblogic服务状态失败", e);
        } catch (ReflectionException e) {
            LOGGER.error("获取weblogic服务状态失败", e);
        } catch (IOException e) {
            LOGGER.error("获取weblogic服务状态失败", e);
        } finally {
            connection = null;
        }
        return iSOk;
    }
    
    /**
     * 测试服务器是否能连通网络
     * 
     * @param hostName ip
     * @return 0是能连通的，1是不能连通的
     * @throws IOException IO异常
     */
    public static int testServerConnection(String hostName) {
        InputStream objIs = null;
        InputStreamReader objIsr = null;
        BufferedReader objBrStat = null;
        int iLine = 3;
        Process objProcess = null;
        hostName = hostName == null ? "127.0.0.1" : hostName;
        String strCmomand = " ping " + hostName;
        try {
            objProcess = CommandTimeoutUtils.commandTimeout(strCmomand, 2, TimeUnit.SECONDS);
            objIs = objProcess.getInputStream();
            objIsr = new InputStreamReader(objIs);
            final Scanner objSc = new Scanner(objIs, "UTF-8");
            while (objSc.hasNext()) {
                String strLine = objSc.nextLine();
                if (strLine.contains("ttl") || strLine.contains("TTL") || strLine.contains("time")) {
                    iLine = 0;
                    break;
                } else if (strLine.startsWith("请求超时") || strLine.startsWith("Request timed out")) {
                    iLine = 3;
                    break;
                }
            }
        } finally {
            if (objProcess != null) {
                objProcess.destroy();
                objProcess = null;
            }
            freeResource(objIs, objIsr, objBrStat);
        }
        return iLine;
    }
    
    /**
     * 释放资源
     * 
     * @param is InputStream流
     * @param isr InputStreamReader流
     * @param br BufferedReader流
     */
    public static void freeResource(InputStream is, InputStreamReader isr, BufferedReader br) {
        try {
            if (is != null) {
                is.close();
            }
            if (isr != null) {
                isr.close();
            }
            if (br != null) {
                br.close();
            }
        } catch (IOException ioe) {
            LOGGER.error("测试服务器连接IO异常", ioe);
        } finally {
            is = null;
            isr = null;
            br = null;
        }
    }
    
}